From b9d828099b291db9bbd76a18efe8f5408f625f06 Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Thu, 12 Aug 2004 14:10:20 +0000 Subject: [PATCH] bitkeeper revision 1.1159.17.18 (411b7a4clSlwGNpVa4jPTa9wgDjfmw) Add compile-time option to use writable pagetables. --- linux-2.6.7-xen-sparse/arch/xen/Kconfig | 6 ++++++ .../arch/xen/i386/kernel/setup.c | 2 +- .../include/asm-xen/asm-i386/page.h | 2 +- .../include/asm-xen/asm-i386/pgalloc.h | 16 +++++++++++++--- .../include/asm-xen/asm-i386/pgtable-2level.h | 7 ++++++- .../include/asm-xen/asm-i386/pgtable.h | 13 +++++++++---- 6 files changed, 36 insertions(+), 10 deletions(-) diff --git a/linux-2.6.7-xen-sparse/arch/xen/Kconfig b/linux-2.6.7-xen-sparse/arch/xen/Kconfig index c1eb03cda1..72733f2efc 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/Kconfig +++ b/linux-2.6.7-xen-sparse/arch/xen/Kconfig @@ -36,6 +36,12 @@ config XEN_PHYSDEV_ACCESS help Device-driver domain (physical device access) +config XEN_WRITABLE_PAGETABLES + bool "Use writable pagetables" + default n + help + Use writable L1 pagetables + endmenu # Xen's block device backend driver needs 2^12 pages diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c index 64cf45c49d..c45654a89e 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c @@ -1104,7 +1104,7 @@ void __init setup_arch(char **cmdline_p) HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); -#if 0 +#ifdef CONFIG_XEN_WRITABLE_PAGETABLES HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writeable_pagetables); #endif diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/page.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/page.h index 17aceff541..c7999f04bd 100644 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/page.h +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/page.h @@ -95,7 +95,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; static inline unsigned long pmd_val(pmd_t x) { unsigned long ret = x.pmd; - if ( (ret & 1) ) ret = machine_to_phys(ret); + if ( (ret) ) ret = machine_to_phys(ret); return ret; } #define pgd_val(x) ({ BUG(); (unsigned long)0; }) diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgalloc.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgalloc.h index c9cc344679..ea933dd2ee 100644 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgalloc.h +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgalloc.h @@ -6,6 +6,7 @@ #include #include #include /* for struct page */ +#include /* for phys_to_virt and page_to_pseudophys */ #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) @@ -15,7 +16,8 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p set_pmd(pmd, __pmd(_PAGE_TABLE + ((unsigned long long)page_to_pfn(pte) << (unsigned long long) PAGE_SHIFT))); - flush_page_update_queue(); /* XXXcl flush */ + flush_page_update_queue(); + /* XXXcl queue */ } /* * Allocate and free page tables. @@ -30,17 +32,25 @@ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long); static inline void pte_free_kernel(pte_t *pte) { free_page((unsigned long)pte); + __make_page_writeable(pte); } static inline void pte_free(struct page *pte) { - __free_page(pte); +#ifdef CONFIG_HIGHPTE + if (pte < highmem_start_page) +#endif + { + __make_page_writeable(phys_to_virt(page_to_pseudophys(pte))); + __free_page(pte); + } } #define __pte_free_tlb(tlb,pte) do { \ tlb_remove_page((tlb),(pte)); \ - flush_page_update_queue(); /* XXXcl flush */ \ + flush_page_update_queue(); \ + /* XXXcl queue */ \ } while (0) /* diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h index 58e51fc2bd..760569f95d 100644 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h @@ -40,8 +40,13 @@ static inline int pgd_present(pgd_t pgd) { return 1; } * within a page table are directly modified. Thus, the following * hook is made available. */ +#ifdef CONFIG_XEN_WRITABLE_PAGETABLES +#define set_pte(pteptr, pteval) (*(pteptr) = pteval) +#define set_pte_atomic(pteptr, pteval) (*(pteptr) = pteval) +#else #define set_pte(pteptr, pteval) queue_l1_entry_update(pteptr, (pteval).pte_low) #define set_pte_atomic(pteptr, pteval) queue_l1_entry_update(pteptr, (pteval).pte_low) +#endif /* * (pmds are folded into pgds so this doesn't get actually called, * but the define is needed for a generic inline function.) @@ -70,7 +75,7 @@ static inline pte_t ptep_get_and_clear(pte_t *xp) { pte_t pte = *xp; if (pte.pte_low) - queue_l1_entry_update(xp, 0); + set_pte(xp, __pte_ma(0)); return pte; } diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h index 9026d62642..ae068a12b2 100644 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -191,7 +191,7 @@ extern unsigned long pg0[]; #define pmd_none(x) (!pmd_val(x)) #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) /* pmd_clear below */ -#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) +#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT)) #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) @@ -241,9 +241,9 @@ static inline int ptep_test_and_clear_young(pte_t *ptep) } static inline void ptep_set_wrprotect(pte_t *ptep) { - unsigned long pteval = *(unsigned long *)ptep; - if ((pteval & _PAGE_RW)) - queue_l1_entry_update(ptep, pteval & ~_PAGE_RW); + pte_t pte = *ptep; + if (pte_write(pte)) + set_pte(ptep, pte_wrprotect(pte)); } static inline void ptep_mkdirty(pte_t *ptep) { @@ -283,6 +283,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) pmd_t p = *(xp); \ set_pmd(xp, __pmd(0)); \ __make_page_writeable((void *)pmd_page_kernel(p)); \ + /* XXXcl queue */ \ } while (0) #ifndef CONFIG_DISCONTIGMEM @@ -401,6 +402,7 @@ static inline void make_page_readonly(void *va) if ( (unsigned long)va >= VMALLOC_START ) __make_page_readonly(machine_to_virt( *(unsigned long *)pte&PAGE_MASK)); + /* XXXcl queue */ } static inline void make_page_writeable(void *va) @@ -412,6 +414,7 @@ static inline void make_page_writeable(void *va) if ( (unsigned long)va >= VMALLOC_START ) __make_page_writeable(machine_to_virt( *(unsigned long *)pte&PAGE_MASK)); + /* XXXcl queue */ } static inline void make_pages_readonly(void *va, unsigned int nr) @@ -421,6 +424,7 @@ static inline void make_pages_readonly(void *va, unsigned int nr) make_page_readonly(va); va = (void *)((unsigned long)va + PAGE_SIZE); } + /* XXXcl queue */ } static inline void make_pages_writeable(void *va, unsigned int nr) @@ -430,6 +434,7 @@ static inline void make_pages_writeable(void *va, unsigned int nr) make_page_writeable(va); va = (void *)((unsigned long)va + PAGE_SIZE); } + /* XXXcl queue */ } static inline unsigned long arbitrary_virt_to_phys(void *va) -- 2.30.2